# -*- coding: utf-8 -*-
# created on 2016/9/23


from mathsolver.functions.base import *
from sympy.abc import x, y, theta
from sympy import tan, atan, pi, sqrt, S, degree, Abs
from mathsolver.functions.root.jiefangchen import JieFangChen
from mathsolver.functions.zhixian.base import default_symbols, ZhiXian


# 判断方程是否是直线
class ZhiXianJudge(BaseFunction):
    def solver(self, *args):
        answer = False
        f1, f2 = args[0].sympify()
        expr = (f1 - f2).expand().simplify()
        symx, symy = default_symbols(expr)
        if expr.is_Add:
            if expr.has(symx) and expr.has(symy):
                expr_cishu = []
                for arg in expr.args:
                    if arg.has(symx) and arg.has(symy):
                        self.steps.append(["", "由直线的定义知，该方程不是直线方程"])
                    else:
                        if arg.has(symx) and not arg.has(symy):
                            symx_degree = degree(arg, gen=symx)
                            expr_cishu.append(symx_degree)
                        elif not arg.has(symx) and arg.has(symy):
                            symy_degree = degree(arg, gen=symy)
                            expr_cishu.append(symy_degree)
                cishu = max(expr_cishu)
                if cishu == 1:
                    self.steps.append(["", "由直线的定义知，该方程是直线方程"])
                    answer = True
                else:
                    self.steps.append(["", "由直线的定义知，该方程不是直线方程"])
                    answer = False
        else:
            if expr.has(symx) and expr.has(symy):
                self.steps.append(["", "由直线的定义知，该方程不是直线方程"])
                answer = False
            elif expr.has(symx) and not expr.has(symy):
                symx_degree = degree(expr, gen=symx)
                if symx_degree == 1:
                    self.steps.append(["", "由直线的定义知，该方程是直线方程"])
                    answer = True
                else:
                    self.steps.append(["", "由直线的定义知，该方程不是直线方程"])
                    answer = False
            elif not expr.has(symx) and expr.has(symy):
                symy_degree = degree(expr, gen=symy)
                if symy_degree == 1:
                    self.steps.append(["", "由直线的定义知，该方程是直线方程"])
                    answer = True
                else:
                    self.steps.append(["", "由直线的定义知，该方程不是直线方程"])
                    answer = False
        self.output.append(BaseVariable(answer))
        self.label.add("判断方程是否是直线")
        return self


# 将直线方程化为一般式
class GetZhiXianYiBanShi(BaseFunction):
    """
    点P(-1,2)到直线8x-6y+15=0的距离为()
    """
    def solver(self, *args):
        zhixian = None
        if len(args) == 1 and isinstance(args[0], BaseLineName):
            name = args[0].sympify()
            zhixian = self.search(name)
        elif len(args) == 1 and isinstance(args[0], BaseEq):
            zhixian = args[0]
        yibanshi = ZhiXian(zhixian).yibanshi.sympify()
        zhixian.value = yibanshi
        self.output.append(zhixian)
        return self


# 求一般式方程的系数
class GetZhiXianCoeff(BaseFunction):
    """
    点P(-1,2)到直线8x-6y+15=0的距离为()
    """
    def solver(self, *args):
        yibanshi = args[0].sympify()
        expr = yibanshi[0]
        symx, symy = default_symbols(expr)
        a = yibanshi[0].coeff(symx)
        b = yibanshi[0].coeff(symy)
        c = (yibanshi[0] - a * symx - b * symy).expand().simplify()
        coeff = [a, b, c]
        self.output.append(BaseValues(coeff))
        return self


# 求直线的法向量
class GetFaXiang(BaseFunction):
    def solver(self, *args):
        coeff = args[0].sympify()
        faxiang_vector = [coeff[0], coeff[1]]
        self.steps.append(
            ["", "∴直线的一个法向量为%s" % (BaseVector({"name": "", "value": faxiang_vector}).printing())])
        self.label.add("求直线的法向量")
        self.output.append(BaseVector({"name": "", "value": faxiang_vector}))
        return self


# 求直线的方向向量
class GetFangXiang(BaseFunction):
    """
    直线x-1=0和直线3x-\\sqrt{3}y+1=0的夹角为()
    """
    def solver(self, *args):
        coeff = args[0].sympify()
        fangxiang_vector = [-coeff[1], coeff[0]]
        self.steps.append(["", "∴直线的一个方向向量为%s" % (BaseVector({"name": "", "value": fangxiang_vector}).printing())])
        self.output.append(BaseVector({"name": "", "value": fangxiang_vector}))
        self.label.add("求直线的方向向量")
        return self


# 根据两点，求向量
class GetXiangLiang(BaseFunction):
    def solver(self, *args):
        point1 = args[0].sympify()
        if isinstance(args[1], str):
            if '原点' in args[1]:
                point2 = [S.Zero, S.Zero]
        else:
            point2 = args[1].sympify()
        vector = [point2[0] - point1[0], point2[1] - point1[1]]
        self.steps.append(["", "经过%s和%s两点的向量为%s" % (BasePoint({"name": "", "value": point1}).printing(), BasePoint({"name": "", "value": point2}).printing(), BaseVector({"name": "", "value": vector}).printing())])
        self.output.append(BaseVector(vector))
        self.label.add("求两点的向量")
        return self


# 根据直线方程求直线斜率
class GetXieLv001(BaseFunction):
    """
    点P(-1,2)到直线8x-6y+15=0的距离为()
    """
    def solver(self, *args):
        a, b, c = args[0].sympify()
        if b != 0:
            xielv = - a / b
            self.steps.append(["", "直线的斜率为%s" % (new_latex(xielv))])
        else:
            self.steps.append(["", "斜率不存在"])
            xielv = S.Infinity
        self.output.append(BasePoly(xielv))
        self.label.add("根据直线方程求直线的斜率")
        return self


class ToBaseFunc(BaseFunction):
    def solver(self, *args):
        value = args[0].sympify()
        self.output.append(BaseEq([y, value]).eq2func())
        return self


class QingXieJiaoRange(BaseFunction):
    def solver(self, *args):
        value_range = args[0].interval
        if not value_range.is_Union:
            left, right, lopen, ropen = value_range.args
            if lopen:
                op_left = "<"
            else:
                op_left = "<="
            if ropen:
                op_right = "<"
            else:
                op_right = "<="
            ineqs = [left, op_left, tan(theta), op_right, right]
            self.steps.append(["", "∴%s" % (BaseIneqs(ineqs).printing())])
            self.output.append(BaseIneqs(ineqs))
        return self


# 根据点的坐标求斜率
class GetXieLv002(BaseFunction):
    def solver(self, *args):
        point1 = None
        point2 = None
        if len(args) == 1 and isinstance(args[0], BasePoints):
            points = args[0].sympify()
            point1 = points[0]
            point2 = points[1]
        elif len(args) == 2 and isinstance(args[0], BasePoint) and isinstance(args[1], BasePoint):
            point1 = args[0].sympify()
            point2 = args[1].sympify()
        elif len(args) == 2 and isinstance(args[0], str):
            if '原点' in args[0]:
                point1 = [S.Zero, S.Zero]
                point2 = args[1].sympify()
        elif len(args) == 1 and isinstance(args[0], BaseLine):
            p1, p2 = args[0].name
            point1 = self.search(p1)
            point1 = point1.sympify()
            point2 = self.search(p2)
            point2 = point2.sympify()
        if point1[0] == point2[0]:
            self.steps.append(["", "斜率不存在"])
            xielv = S.Infinity
            self.output.append(BaseValue(xielv))
        else:
            xielv = (point2[1] - point1[1]) / (point2[0] - point1[0])
            self.steps.append(["", "直线斜率为 %s" % (new_latex(xielv))])
        self.label.add("根据两点坐标求直线斜率")
        self.output.append(BaseValue(xielv))
        return self


# 根据倾斜角求直线斜率
class GetXieLv003(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseEq):
            eq = args[0].sympify()
            qingxiejiao = eq[1]
        else:
            qingxiejiao = args[0].sympify().args[0]
        xielv = tan(qingxiejiao / 180 * pi)
        self.steps.append(["", "∵ 直线的倾斜角为%s度" % new_latex(qingxiejiao)])
        self.steps.append(["", "∴ 直线斜率为%s" % (new_latex(xielv))])
        self.label.add("根据直线的倾斜角求直线斜率")
        self.output.append(BasePoly(xielv))
        return self


# 求直线的倾斜角
class GetQingXieJiao(BaseFunction):
    """
    直线l的方程是y=x-1,则直线l的倾斜角为()
    """
    def solver(self, *args):
        xielv = args[0].sympify()
        qxj = BasePoly(atan(xielv))
        self.output.append(qxj)
        self.label.add("求直线的倾斜角")
        return self


# 求直线的截距
class GetJieJu(BaseFunction):
    """
    直线2x-3y=6在y轴上的截距为()
    """
    def solver(self, *args):
        if isinstance(args[0], BaseVariable):
            line_name = args[0].value
            zhixian = self.search(line_name)
            f1, f2 = zhixian.sympify()
        else:
            f1, f2 = args[0].sympify()
        if isinstance(args[1], BaseAxis):
            axis = args[1].value
        else:
            axis = args[1]
        if "x" in axis:
            self.target = y
            new_f1 = f1.subs(x, 0)
            new_f2 = f2.subs(x, 0)
            stepsolver = JieFangChen().solver(BaseEq([new_f1, new_f2]), BaseValue("y"))
            jie = stepsolver.output[0].value
            jieju = jie[list(jie.keys())[0]].args[0]
            self.output.append(BasePoly(jieju))
            self.steps.append(["", "直线在%s轴上的截距为%s" % (new_latex(y), new_latex(jieju))])
            self.label.add("求直线在坐标轴的截距")
        elif "y" in axis:
            new_f1 = f1.subs(y, 0)
            new_f2 = f2.subs(y, 0)
            stepsolver = JieFangChen().solver(BaseEq([new_f1, new_f2]))
            jie = stepsolver.output[0].value
            jieju = jie[list(jie.keys())[0]].args[0]
            self.output.append(BasePoly(jieju))
            self.steps.append(["", "直线在%s轴上的截距为%s" % (new_latex(x), new_latex(jieju))])
            self.label.add("求直线在坐标轴的截距")
        return self


# 求两点的中点
class GetZhongDian(BaseFunction):
    def solver(self, *args):
        if len(args) == 1 and isinstance(args[0], BaseLine):
            line_left, line_right = args[0].name
            point1 = self.search(line_left)
            point1 = point1.sympify()
            point2 = self.search(line_right)
            point2 = point2.sympify()
        elif len(args) == 1 and isinstance(args[0], BasePoints):
            points = args[0].sympify()
            point1 = points[0]
            point2 = points[1]
        elif len(args) == 2:
            point1 = args[0].sympify()
            point2 = args[1].sympify()
        zhongdian = [(point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2]
        self.steps.append(["", "由中点公式知，中点为%s" % (BasePoint({"name": "", "value": zhongdian}).printing())])
        self.label.add("求两点的中点")
        self.output.append(BasePoint({"name": "", "value": zhongdian}))
        return self


# 求两点的距离
class GetLiangDianJuLi(BaseFunction):
    """
    已知点A(1,2),B(3,4).求AB的长度.
    """
    def solver(self, *args):
        if len(args) == 1 and isinstance(args[0], BasePoints):
            points = args[0].sympify()
            point1 = points[0]
            point2 = points[1]
        elif len(args) == 1 and isinstance(args[0], BaseLine):
            left, right = args[0].name
            point1 = self.search(left)
            point1 = point1.sympify()
            point2 = self.search(right)
            point2 = point2.sympify()
        elif len(args) == 2:
            point1 = args[0].sympify()
            point2 = args[1].sympify()
        liangdianjuli = sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2)
        self.steps.append(["", "由两点距离公式知，%s 和 %s 的距离为 %s" % (
            BasePoint({"name": "", "value": [point1[0], point1[1]]}).printing(),
            BasePoint({"name": "", "value": [point2[0], point2[1]]}).printing(),
            new_latex(liangdianjuli))])
        self.label.add("求两点距离")
        self.output.append(BasePoly(liangdianjuli))
        return self


# 根据截距求截距坐标
class JieJuZuoBiao(BaseFunction):
    def solver(self, *args):
        axis = args[0].value
        value = args[1].sympify()
        if 'y轴' in axis:
            self.steps.append(["", "∴直线在y轴上的坐标为%s" % (
                BasePoint({"name": "", "value": [S.Zero, value]}).printing())])
            self.output.append(BasePoint({"name": "", "value": [S.Zero, value]}))
        elif 'x轴' in axis:
            self.steps.append(["", "∴直线在x轴上的坐标为%s" % (
                BasePoint({"name": "", "value": [value, S.Zero]}).printing())])
            self.output.append(BasePoint({"name": "", "value": [value, S.Zero]}))
        self.label.add("根据截距求截距坐标")
        return self


# 求三角形的面积
class AreaOfTriangle(BaseFunction):
    """
    直线2x-y+2=0与坐标轴围成的三角形的面积是()
    """
    def solver(self, *args):
        a1 = args[0].sympify()
        a2 = args[1].sympify()
        mianji = Abs(a1) * Abs(a2) / 2
        self.steps.append(["", "由三角形的面积公式知面积为%s" % (new_latex(mianji))])
        self.label.add("求三角形面积")
        self.output.append(BasePoly(mianji))
        return self


if __name__ == '__main__':
    pass
